/* Copyright Paul Reiche, Fred Ford. 1992-2002, Christopher Night 2013

This file is part of the HTML5 port of Ur-Quan Masters (UQM-HTML5)

UQM-HTML5 is free software: you can redistribute it and/or modify it under the terms of the GNU
General Public License as published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.

UQM-HTML5 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with this program.  If not,
see <http://www.gnu.org/licenses/>. */

// port of src/uqm/misc.c

var NEUTRAL_PLAYER_NUM = -1

function Asteroid() {
	this.state = {
		APPEARING: true,
	}
	this.frames = graphics.getfarray("lbm/astbig.ani")
	// The original seemed to choose an asteroid location in a box outside the screen.
	// This chooses one in a circle outside the screen.
	var theta = Math.random() * tau
	this.frame_index = Math.floor(Math.random() * 16)
	this.current = {
		x: process.camera.x0 + 0.7 * ARENA_WIDTH * Math.sin(theta),
		y: process.camera.y0 + 0.7 * ARENA_HEIGHT * Math.cos(theta),
		frame: this.frames[this.frame_index],
	}
	this.current.px = Math.round(this.current.x)
	this.current.py = Math.round(this.current.y)
	this.next = {
		x: this.current.x,
		y: this.current.y,
		px: Math.round(this.current.x),
		py: Math.round(this.current.y),
		frame: this.current.frame,
	}

	var v = Math.random() * 8 + 4, phi = Math.random() * tau
	this.vx = v * Math.sin(phi)
	this.vy = v * Math.cos(phi)
	this.turn_wait = this.turn_t = Math.floor(Math.random() * 3)
	this.clockwise = Math.random() < 0.5
	//console.log(this.vx, this.vy)
}
Asteroid.prototype = {
	playerNr: NEUTRAL_PLAYER_NUM,
	hit_points: 1,
	mass: 3,
	life_span: 1, // NORMAL_LIFE,
	preprocess_func: function () {
		if (this.turn_wait > 0) {
			--this.turn_wait
			return
		}
		this.frame_index = rmod(this.frame_index + (this.clockwise ? 1 : -1), 16)
		this.next.frame = this.frames[this.frame_index]
		this.turn_wait = this.turn_t
	},
	postprocess_func: function () {
	},
	collision_func: function () {
	},
	death_func: function () {
		elements.push(new Rubble(this))
	},
}

function Rubble(asteroid) {
	this.state = {
		SKIP_COLLISION: true,
		APPEARING: true,
		FINITE_LIFE: true,
		NONSOLID: true,
	}
	this.life_span = 4  // was 5?
	this.turn_wait = this.next_turn = 0
	this.farray = asteroid.frames
	this.frame_index = 16
	this.current = {
		x: asteroid.current.x,
		y: asteroid.current.y,
		frame: this.farray[this.frame_index],
	}
}
Rubble.prototype = {
	preprocess_func: ship.animation_preprocess,
	death_func: function () { misc.spawn_asteroid() },
}

function Planet() {
	this.frames = graphics.getfarray("lbm/ool__big.ani")
	this.state = {
		APPEARING: true,
		GRAVITY_MASS: true,
	}
	this.current = {
		x: Math.random() * ARENA_WIDTH,  // TODO: time space matter conflicts
		y: Math.random() * ARENA_HEIGHT,
		frame: this.frames[0],
	}
	this.next = {
		x: this.current.x,
		y: this.current.y,
		frame: this.current.frame,
	}
	this.current.px = this.next.px = Math.round(this.current.x)
	this.current.py = this.next.py = Math.round(this.current.y)
	this.vx = this.vy = 0
}
Planet.prototype = {
	playerNr: NEUTRAL_PLAYER_NUM,
	mass: 200,  // Determines elasticity of objects that bounce off it
	GRAVITY_THRESHOLD: 255,
	gravitystrength: 1,
	hit_points: 200,
	life_span: 2,  // NORMAL_LIFE + 1?
	// Taken from uqm/gravity.c:CalculateGravity
	postprocess_func: function () {
		for (var j = 0 ; j < elements.length ; ++j) {
			var element = elements[j]
			if (element === this) continue
			if (element.state.SKIP_COLLISION) continue
			var estate = element.state.PRE_PROCESS ? element.current : element.next
			var dx = zmod(estate.x - this.current.x, ARENA_WIDTH)
			var dy = zmod(estate.y - this.current.y, ARENA_HEIGHT)
			var d2 = dx * dx + dy * dy
			if (d2 > this.GRAVITY_THRESHOLD * this.GRAVITY_THRESHOLD) continue
			var d = Math.sqrt(d2)
			// I'm skipping a lot of arithmetic here that doesn't seem to get used.
			element.vx -= this.gravitystrength * dx / d * 0.25
			element.vy -= this.gravitystrength * dy / d * 0.25
			if (element.state.PLAYER_SHIP) {
				element.status.SHIP_AT_MAX_SPEED = false
				element.status.SHIP_IN_GRAVITY_WELL = true
			}
		}
	},
	collision_func: function () {
	},
}


var misc = {
	spawn_asteroid: function () {
		elements.push(new Asteroid())
	},
	spawn_planet: function () {
		elements.push(new Planet())
	},
	do_damage: function (element, damage) {
		if (element.state.PLAYER_SHIP) {
			// TODO: move this to status.DeltaCrew
			element.crew_level = Math.max(element.crew_level - damage, 0)
			if (!element.crew_level) {
				element.life_span = 0
				element.state.NONSOLID = true
			}
		} else if (!element.state.GRAVITY_MASS) {
			//console.log(element, element.hit_points, damage)
			element.hit_points = Math.max(element.hit_points - damage, 0)
			if (!element.hit_points) {
				element.life_span = 0
				element.state.NONSOLID = true
			}
		}
	},
}

